//============================================================================
// Name        : ai_manager.cpp
// Author      : dhelmer
//============================================================================

// INCLUDES //

#include "ai/ai_manager.h"
#include "effects_manager.h"
#include "util.h"

#include <iostream>
#include <vector>
//////////////

using namespace std;

// Singleton Pointer
AIManager* AIManager::instance = NULL;

// Private Constructor
AIManager::AIManager()
{
	timeToNextAction = AI_DELAY;
	
	//currentDeck = aiDeck = totalDeck = 0;
	
	mainDeck = new Deck ();
	discardDeck = new Deck ();
	alignmentLevels.reserve(MAX_COLORS);
}

// Singleton Accessor
AIManager* AIManager::GetManager()
{
	if (instance == NULL)
	{
		instance = new AIManager();
	}
	return instance;
}

// Deconstructor
AIManager::~AIManager()
{	
	if (deck)
	{
		delete deck;
		deck = NULL;
	}
	
	if (mainDeck)
	{
		delete mainDeck;
		mainDeck = NULL;
	}
	
	if (discardDeck)
	{
		delete discardDeck;
		discardDeck = NULL;
	}
	
	for( int i = 0; i < (int)cardQueue.size(); i++ )
	{
		delete cardQueue[i];
	}
}

////////
// Deck management
////////
/*
* Loads an initial set of cards into the deck.
* 
* @param cards The cards to add.
**/
void AIManager::LoadCards(vector<CardInfo*> cards)
{
	mainDeck->Add(cards);
	mainDeck->Shuffle();
}

/*
* Pops the top card from the deck and returns it.
* 
* @return The top card.
**/
Card* AIManager::PopCard()
{
	if( mainDeck->GetSize() == 0 )
	{
		while( discardDeck->GetSize() > 0 )
		{
			mainDeck->Add(discardDeck->Remove());
		}
		
		mainDeck->Shuffle();
	}
	
	if( mainDeck->GetSize() == 0 )
	{
		return NULL;
	}
	else
	{
		Card* card = new Card(mainDeck->Remove());
		
		
		return card;
	}
}

void AIManager::PlayCard(int cardIndex)
{
	
	CardInfo* info = ((Card*)cardQueue[cardIndex])->GetInfo();
	((Card*)cardQueue[cardIndex])->ClearInfo();
	cardQueue.erase(cardQueue.begin()+cardIndex);
	for( int i = 0; i < (int)info->GetEffects().size(); i++ )
	{
		info->GetEffects()[i]->level = 1;
	}
		
	EffectsManager::GetManager()->CardActivated(info, false);
	
	Discard (info);
	
	GrabCards();
}

int AIManager::GetColorIndex(char color)
{
	int colorIndex = -1;
	switch( color )
	{
	case 'r':
	case 'R':
		colorIndex = 0;
		break;
	case 'b':
	case 'B':
		colorIndex = 1;
		break;
	case 'g':
	case 'G':
		colorIndex = 2;
		break;
	case 'y':
	case 'Y':
		colorIndex = 3;
		break;
	case 'w':
	case 'W':
		colorIndex = 4;
		break;
	case 'l':
	case 'L':
		colorIndex = 5;
		break;
	default:
		break;
	}	
	return colorIndex;
}

/**
* Attempts to fill the hand with cards.
**/
void AIManager::GrabCards()
{
	int num = MAX_HAND_SIZE;
	if( num > 0 )
	{
		for( int i = 0; i < num; i++ )
		{
			Card* card = PopCard();
			if( card ){
				cardQueue.insert(cardQueue.begin(), card);
			}
		}
	}
}

// Effect State Change
void AIManager::EffectStateChanged ( Effect* effect )
{
	
	if (effect->GetId() == EFFECT_ALIGNMENT_CHANGE && effect->GetTrigger() == effect->state)
	{

		vector<string> target = Util::Split( effect->GetTarget(), ',' );
		if( (int)target.size() > 1 && target[1] == EFFECT_TARGET_ENEMY )
		{
			string action = ((AlignmentChangeEffect*)effect)->GetChange()[effect->level];
			char c = action[0];
			int amount = atoi(action.erase(0, 1).c_str());
			
			int colorIndex = GetColorIndex(c);
			alignmentLevels[colorIndex]+=amount;
		}
	}
}

// TimePassed
void AIManager::TimePassed ( int ms )
{
	timeToNextAction = timeToNextAction - ms;
	
	if (timeToNextAction < 0)
	{
		PlayCard (rand() % cardQueue.size());

		
		timeToNextAction = AI_DELAY;
	}
}
